<template>
  <el-table ref="table" v-bind="tableProps" v-on="$listeners">
    <template v-for="column in columns">
      <template v-if="column.type">
        <template v-if="['index', 'selection', 'expand'].includes(column.type)">
          <el-table-column :key="column.key" v-bind="column" />
        </template>
        <template v-else-if="column.type === 'button'">
          <el-table-column :key="column.key" v-bind="column">
            <template slot-scope="scope">
              <el-button
                v-for="btn in getShowBtns(column.buttons, scope.row)"
                :key="btn.key"
                v-bind="btn"
                @click="buttonClick(btn.key, scope.$index, scope.row)"
              >
                {{ btn.caption }}
              </el-button>
              <template v-if="!getShowBtns(column.buttons, scope.row).length">
                {{ column.emptyCellValue || emptyCellValue }}
              </template>
            </template>
          </el-table-column>
        </template>
      </template>
      <template v-else>
        <el-table-column :key="column.key" v-bind="column">
          <template slot-scope="scope">
            <tn-render-cell
              v-if="column.render"
              :row="scope.row"
              :column="column"
              :index="scope.$index"
            />
            <template v-else>
              {{ getNoEmptyCellValue(scope.row, column) }}
            </template>
          </template>
        </el-table-column>
      </template>
    </template>
    <slot />
  </el-table>
</template>

<script>
  import ElementUi from 'element-ui'
  import elementResizeDetectorMaker from 'element-resize-detector'

  import { validateParam } from '@utils'

  import TnRenderCell from './render-cell'

  const elTableProps = ElementUi?.Table?.props || {
    data: {
      type: Array,
      default: function () {
        return []
      }
    }
  }

  const tnTableProps = ['columns', 'emptyCellValue', 'autoHeight']

  export default {
    name: 'TnELtable',
    components: {
      TnRenderCell
    },
    props: {
    ...elTableProps,
    columns: {
      type: Array,
      default: () => []
    },
    emptyCellValue: {
      type: String,
      default: '--'
    },
    autoHeight: {
      type: Boolean,
      default: true
    }
    },
    data () {
      return {
        tableHeight: 200
      }
    },
    computed: {
      fromParentVmTableProps () {
        return Object.keys(this.$props).reduce((tableProps, pName) => {
          if (!tnTableProps.includes(pName)) {
            tableProps[pName] = this[pName]
          }
          return tableProps
        }, {})
      },
      tableProps () {
        return {
        ...this.fromParentVmTableProps,
        ...(this.autoHeight
          ? {
              height: this.tableHeight
            }
          : {})
        }
      }
    },
    watch: {
      columns: {
        handler (val, oldVal) {
          this.$nextTick(() => {
            this.tableVm.doLayout()
          })
        }
      },
      data: {
        handler (val, oldVal) {
          this.$nextTick(() => {
            this.tableVm.$refs.bodyWrapper.scrollTo(0, 0)
          })
        }
      }
    },
    mounted () {
      this.detectParantNodeResize()
      this.tableVm = this.$refs.table
    },
    methods: {
      getCellValue (row, column) {
        const { caption, prop } = column
        return validateParam(caption)
          ? typeof caption === 'function'
            ? caption(row)
            : row[caption] || caption
          : row[prop]
      },
      getNoEmptyCellValue (row, column) {
        const value = this.getCellValue(row, column)
        return validateParam(value) ? value : this.emptyCellValue
      },
      buttonClick (btnKey, index, row) {
        this.$emit('button-click', btnKey, index, row)
      },
      // 这个方法用来动态设置 tableHeight
      getAutoHeight (elParent) {
        const pt = this.getStyle(elParent, 'paddingTop')
        const pb = this.getStyle(elParent, 'paddingBottom')
        const siblingsHeight = Array.from(elParent.children).reduce(
          (acc, item) => {
            if (
              item.classList.contains('el-table') ||
              !!item?.getAttribute('aria-hidden')
            ) {
              return acc
            } else {
              return acc + item.clientHeight
            }
          },
          0
        )
        this.$nextTick(() => {
          this.tableHeight =
            elParent.clientHeight - (pt + pb + siblingsHeight) + 'px'
        })
      },
      // 获取样式 我们需要减掉 padding-top， padding-bottom的值
      getStyle (obj, attr) {
        // 兼容IE浏览器
        const result = obj.currentStyle
          ? obj.currentStyle[attr].replace('px', '')
          : document.defaultView
            .getComputedStyle(obj, null)[attr].replace('px', '')
        return Number(result)
      },
      detectParantNodeResize () {
        // 创建实例
        const erd = elementResizeDetectorMaker()
        const _this = this
        // 监听id为test的元素 大小变化
        erd.listenTo(this.$el.parentNode, function (element) {
          window.ele = element
          _this.getAutoHeight(element)
        })
      },
      getShowBtns (btns = [], row) {
        return btns.filter(
          (btn) =>
            !!(typeof btn.hidden === 'function'
              ? btn.hidden(row)
              : btn.hidden) === false
        )
      }
    }
  }
</script>

<style></style>
